1. Field of the Invention
The present invention relates to a system for intercepting one or more application program interface (API) calls in a virtual memory environment.
2. Description of the Related Art
FIG. 1 shows the address space layout for a conventional virtual memory system of the type employed in, for example, OS/2 clients and uniprocessor servers prior to OS/2 Warp Version 4.5.
In such systems, virtual memory is divided into a system area occupying addresses between 4 GB and 512 MB, shared memory occupying addresses between 512 MB to 64 MB and private memory typically occupying the lowest 64 MB addresses. (The upper boundary of the private memory may expand above 64 MB at the expense of shared memory during normal system operation, although throughout this document the size of the private area will be stated as the initial size of 64 MB.) The shared area is subdivided into a global shared region (GSR) and a general purpose (GP) shared region. Virtual and physical memory is further divided into pages typically 4K in size. Each application process uses shared and private memory for its executable code and data and uses a set of page tables stored in the system area for mapping the virtual memory locations into physical memory and also for storing a process's access rights to memory. The mapping for pages in the GSR and the system area is common to all processes whereas the mapping for pages in private memory is potentially unique for each process. In the case of GP shared memory, its organization is common to all processes, however, only global data is mapped commonly; instance data is mapped uniquely for each process.
When the system switches a process context, the outgoing process's unique page table entries are saved in the system area while the incoming process's are refreshed from copies in the system area. On an Intel platform, Control Register 3 locates the page tables and the per process copies of the unique page mappings, which are used to update the page tables in a process context switch.
The kernel is loaded into the system area, access to which requires system privilege and special instructions to access kernel APIs. Most compilers are designed to generate code that accesses non-privileged APIs, thus all kernel APIs have to be front-ended by employing an API exposed by a shared memory module. In the case of OS/2 the module is called DOSCALL1.DLL. DOSCALL1 converts “near” type function calls to “far” type function calls required to access system kernel functions. When in memory, along with other code segments in shared memory, DOSCALL1 code segments are marked read-only and so their operation cannot easily be altered by application processes. Nonetheless, indirection of kernel APIs via DOSCALL1 affords the facility for moving function between the kernel and DOSCALL1 and other system modules without requiring any recompilation of application code.
Whereas older versions of OS/2 implement only low memory for application use, OS/2 Warp Version 3.0 SMP and Warp Version 4.5 introduce high memory regions for shared and private use by 32-bit applications only, FIG. 2. The total high memory space is limited to a maximum of 2.5 GB, which together with the 512 MB low memory (compatibility) region allows a 32-bit application to access 3 GB of virtual storage. However, it should be noted that access to high memory regions requires deliberate action on the part of applications. By default, memory allocations are made from the 512 MB compatibility region and this restriction of the application space (private and shared areas) ensures compatibility with older 16-bit applications.
Because versions prior to OS/2 Warp Version 3.0 SMP and Warp Version 4.5 only allow access to low memory regions, many applications continue to use that region even when executing on a later version that supports high memory. This can give rise to memory shortage problems, especially with long-running applications such as Lotus Domino that allocate their heaps in the low shared area.
A heap is a chunk of virtual memory, which is sub-allocated into sections or blocks of varying size. Lotus Domino allocates a heap in chunks of 1 MB to avoid the overhead of system memory allocation, which has not only a time overhead due to its generic nature, but also a granularity overhead, the granularity of system allocation usually being some multiple of a page size (4K). Problems arise with heap technologies when blocks of various sizes are sub-allocated from the same heap. Over time, this leads to fragmentation of the heap, the degree of which is dependent on the pattern of heap usage. In the case of Lotus Domino, wastage due to fragmentation was found to be approximately 30%. Once the heap is badly fragmented the maximum block size becomes severely limited. The only recourse when this happens is to allocate an additional heap. Lotus Domino does this to the extent that it will eventually expand the number of heaps to around 300 1 MB heaps—i.e. 300 MB of virtual memory in total. Lotus Domino makes its heap allocations in the low shared area for backwards compatibility with earlier versions of OS/2 and other operating systems that do not provide a high shared area. Under normal operating conditions, OS/2 allows Lotus Domino to acquire a maximum of approximately 250 MB (depending upon concurrent demand) from the low shared area and once this limit is reached unpredictable failures occur.
However, rather than recompile such applications, for example, it would be useful to intercept their heap allocations and redirect them from the low shared region to the high shared region.
Interception of APIs in itself is not a unique idea, in fact, it is well known on MS-DOS platforms to alter the address of an interrupt service routine in an interrupt vector table, have alternative code at the altered address process an interrupt request and then redirect the request to the original address in the interrupt vector table for further processing. Typically, however, such machines need to be rebooted if the interception is to be either disabled or reconfigured. In server systems or other systems, however, where availability is critical, it is not acceptable to require users to restart the system when interception characteristics are altered.